﻿// --------------------------------------------------------------------------------------------------------------------
// <copyright file="UnsafeBitmap.cs" company="Voogd en Voogd Diensten">
//   Copyright 2008-2009 Voogd en Voogd Diensten
// </copyright>
// <author>Jelle</author>
// <summary>
//   De UnsafeBitmap class.
// </summary>
// --------------------------------------------------------------------------------------------------------------------

namespace GLCDST7565Plugin
{
    using System;
    using System.Collections.Generic;
    using System.Drawing;
    using System.Drawing.Imaging;
    using System.Linq;
    using System.Text;

    /// <summary>
    /// Implementeert de UnsafeBitmap
    /// </summary>
    public unsafe class UnsafeBitmap
    {
        /// <summary>
        /// Bitmap
        /// </summary>
        Bitmap bitmap;

        /// <summary>
        /// three elements used for MakeGreyUnsafe
        /// </summary>
        int width;

        /// <summary>
        /// Bitmap data
        /// </summary>
        BitmapData bitmapData = null;

        /// <summary>
        /// P base
        /// </summary>
        Byte* pBase = null;

        /// <summary>
        /// Initialiseert een nieuwe instantie van de UnsafeBitmap class
        /// </summary>
        /// <param name="bitmap">De Bitmap param van het type Bitmap</param>
        public UnsafeBitmap(Bitmap bitmap)
        {
            this.bitmap = new Bitmap(bitmap);
        }

        /// <summary>
        /// Initialiseert een nieuwe instantie van de UnsafeBitmap class
        /// </summary>
        /// <param name="width">De Width param van het type int</param>
        /// <param name="height">De Height param van het type int</param>
        public UnsafeBitmap(int width, int height)
        {
            this.bitmap = new Bitmap(width, height, PixelFormat.Format24bppRgb);
        }

        /// <summary>
        /// Dispose
        /// </summary>
        public void Dispose()
        {
            bitmap.Dispose();
        }

        /// <summary>
        /// Leest of schrijft Bitmap
        /// </summary>
        public Bitmap Bitmap
        {
            get
            {
                return (bitmap);
            }
        }

        /// <summary>
        /// Leest of schrijft PixelSize
        /// </summary>
        private Point PixelSize
        {
            get
            {
                GraphicsUnit unit = GraphicsUnit.Pixel;
                RectangleF bounds = bitmap.GetBounds(ref unit);

                return new Point((int)bounds.Width, (int)bounds.Height);
            }
        }

        /// <summary>
        /// Lock bitmap
        /// </summary>
        public void LockBitmap()
        {
            GraphicsUnit unit = GraphicsUnit.Pixel;
            RectangleF boundsF = bitmap.GetBounds(ref unit);
            Rectangle bounds = new Rectangle((int)boundsF.X,
           (int)boundsF.Y,
           (int)boundsF.Width,
           (int)boundsF.Height);

            // Figure out the number of bytes in a row
            // This is rounded up to be a multiple of 4
            // bytes, since a scan line in an image must always be a multiple of 4 bytes
            // in length. 
            width = (int)boundsF.Width * sizeof(PixelData);
            if (width % 4 != 0)
            {
                width = 4 * (width / 4 + 1);
            }
            bitmapData =
           bitmap.LockBits(bounds, ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);

            pBase = (Byte*)bitmapData.Scan0.ToPointer();
        }

        /// <summary>
        /// Get pixel
        /// </summary>
        /// <param name="x">De X param van het type int</param>
        /// <param name="y">De Y param van het type int</param>
        /// <returns>Retourneert Pixel data</returns>
        public PixelData GetPixel(int x, int y)
        {
            PixelData returnValue = *PixelAt(x, y);
            return returnValue;
        }

        /// <summary>
        /// Set pixel
        /// </summary>
        /// <param name="x">De X param van het type int</param>
        /// <param name="y">De Y param van het type int</param>
        /// <param name="colour">De Colour param van het type PixelData</param>
        public void SetPixel(int x, int y, PixelData colour)
        {
            PixelData* pixel = PixelAt(x, y);
            *pixel = colour;
        }

        /// <summary>
        /// Unlock bitmap
        /// </summary>
        public void UnlockBitmap()
        {
            bitmap.UnlockBits(bitmapData);
            bitmapData = null;
            pBase = null;
        }

        /// <summary>
        /// Pixel at
        /// </summary>
        /// <param name="x">De X param van het type int</param>
        /// <param name="y">De Y param van het type int</param>
        /// <returns>Retourneert </returns>
        public PixelData* PixelAt(int x, int y)
        {
            return (PixelData*)(pBase + y * width + x * sizeof(PixelData));
        }
    }

    /// <summary>
    /// Pixel data
    /// </summary>
    public struct PixelData
    {
        /// <summary>
        /// Blue
        /// </summary>
        public byte blue;

        /// <summary>
        /// Green
        /// </summary>
        public byte green;

        /// <summary>
        /// Red
        /// </summary>
        public byte red;
    }
}
